﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;
using System.IO;
using System.Security.Permissions;
using System.Configuration;

namespace Koossery.MVCwin.Util
{
    /// <summary>
    /// Read an XML file from the xml element and the xml attribute
    /// </summary>
    public class XmlUtility
    {
        // Fields
        private static volatile Hashtable _configFileHashTable;
        private const string PROTOCOL_SEPARATOR = "://";

        // Methods
        static XmlUtility()
        {
            _configFileHashTable = null;
        }

        public XmlUtility()
        {
        }

        private static bool FileExists(string filePath)
        {
            if (File.Exists(filePath))
            {
                return true;
            }
            FileIOPermission permission = null;
            try
            {
                permission = new FileIOPermission(FileIOPermissionAccess.Read, filePath);
            }
            catch
            {
                return false;
            }
            try
            {
                permission.Demand();
            }
            catch (Exception exception)
            {
                throw new ConfigurationException(string.Format("Doesn't have the right to read the config file \"{0}\". Cause : {1}", filePath, exception.Message), exception);
            }
            return false;
        }

        private static XmlDocument GetConfigAsXmlDocument(string resourcePath)
        {
            XmlDocument document = new XmlDocument();
            XmlTextReader reader = null;
            try
            {
                try
                {
                    reader = new XmlTextReader(resourcePath);
                    document.Load(reader);
                }
                catch (Exception exception)
                {
                    throw new ConfigurationException(string.Format("Unable to load config file \"{0}\". Cause : {1}", resourcePath, exception.Message), exception);
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return document;
        }

        private static string GetFileSystemResourceWithoutProtocol(string filePath)
        {
            int index = filePath.IndexOf("://");
            if (index == -1)
            {
                return filePath;
            }
            if (filePath.Length > (index + "://".Length))
            {
                while (filePath[++index] == '/')
                {
                }
            }
            return filePath.Substring(index);
        }

        public static string getKeyValueFromXmlConfigFile(string configFileName, string xmlNodeName, string key)
        {
            string attribute;
            try
            {
                configFileName = GetFileSystemResourceWithoutProtocol(configFileName);
                XmlDocument document = null;
                if (_configFileHashTable != null)
                {
                    document = (XmlDocument)_configFileHashTable[configFileName];
                }
                if ((document == null) || (_configFileHashTable == null))
                {
                    lock (typeof(Hashtable))
                    {
                        if ((document == null) || (_configFileHashTable == null))
                        {
                            LoadAndCacheXmlConfigFile(configFileName);
                            document = (XmlDocument)_configFileHashTable[configFileName];
                        }
                    }
                }
                XmlNodeList elementsByTagName = document.GetElementsByTagName(xmlNodeName);
                XmlNodeReader reader = null;
                attribute = null;
                foreach (XmlNode node in elementsByTagName)
                {
                    reader = new XmlNodeReader(node);
                    reader.Read();
                    attribute = reader.GetAttribute(key);
                    attribute.Trim();
                }
            }
            catch (Exception exception)
            {
                throw new ConfigurationException("Message not found for key =" + key + ": " + exception.Message);
            }
            return attribute;
        }

        private static void LoadAndCacheXmlConfigFile(string xmlConfigFile)
        {
            xmlConfigFile = GetFileSystemResourceWithoutProtocol(xmlConfigFile);
            FileExists(xmlConfigFile);
            XmlDocument configAsXmlDocument = GetConfigAsXmlDocument(xmlConfigFile);
            if (_configFileHashTable == null)
            {
                _configFileHashTable = new Hashtable();
            }
            _configFileHashTable[xmlConfigFile] = configAsXmlDocument;
        }
    }
}
